// ==UserScript==
// @name         小说小助手（手机版）
// @namespace    http://tampermonkey.net/
// @version      3.3.0-mobile
// @description  手机版小说下载助手，支持更多网站和断点续传功能，添加预览高亮功能
// @match        http://*/*
// @match        https://*/*
// @grant        GM_xmlhttpRequest
// @grant        GM_download
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        unsafeWindow
// ==/UserScript==

(function() {
    'use strict';

    // 检查是否已经初始化
    if (window.self !== window.top) {
        console.log('脚本在iframe中运行，跳过执行');
        return;
    }

    // 防止脚本重复执行
    if (unsafeWindow.__NovelHelperInitialized) {
        console.log('脚本已初始化，跳过重复执行');
        return;
    }
    unsafeWindow.__NovelHelperInitialized = true;

    // 元数据标记
    const METADATA_MARKER = '<!-- NOVEL_HELPER_METADATA:';
    const METADATA_END = '-->';

    // 状态管理
    const state = {
        isProcessing: false,
        chaptersExtracted: 0,
        cancelRequested: false,
        extractedContent: "",
        lastChapterUrl: "",
        maxRetries: 3,
        isResuming: false,        // 是否正在恢复下载
        resumeContent: "",        // 恢复下载时的已有内容
        resumeUrl: "",            // 恢复下载时的起始URL
        filters: [],              // 用户定义的过滤条件
        previewMode: false        // 是否处于预览模式
    };

    // 配置设置
    const config = {
        defaultTimeout: 8000,     // 默认超时时间 (毫秒)
        minChapterLength: 20,     // 章节最小长度 (字符)
        maxChapters: 5000,        // 最大章节数防止无限循环
        maxPreviewLength: 10000   // 最大预览长度
    };

    // 创建Shadow Root的辅助函数
    function createShadowHost() {
        const host = document.createElement('div');
        document.body.appendChild(host);
        return host.attachShadow({ mode: 'open' });
    }

    // 添加样式到Shadow DOM
    function addStylesToShadow(shadowRoot, css) {
        const style = document.createElement('style');
        style.textContent = css;
        shadowRoot.appendChild(style);
    }

    // 所有UI样式（已针对移动端优化）
    const UI_STYLES = `
        :host {
            all: initial;
        }

        .novel-helper-ui {
            position: fixed;
            bottom: 0;
            left: 0;
            right: 0;
            width: 100%;
            z-index: 10000;
            background: #ffffff;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            box-shadow: 0 -2px 15px rgba(0, 0, 0, 0.08);
            border-radius: 12px 12px 0 0;
            overflow: hidden;
            border: 1px solid #eaeaea;
            display: flex !important;
            flex-direction: column;
            height: auto !important;
            max-height: 80vh;
        }

        .nh-container {
            padding-bottom: 20px;
            background: #fff;
            display: flex;
            flex-direction: column;
            height: 100%;
            position: relative !important;
        }

        .nh-header {
            padding: 15px 20px;
            background: #f8f8f8;
            border-bottom: 1px solid #eee;
            display: flex;
            justify-content: space-between;
            align-items: center;
            cursor: move;
            user-select: none;
            touch-action: none;
        }

        .nh-title {
            font-weight: 600;
            font-size: 16px;
            color: #333;
            letter-spacing: 0.3px;
        }

        .nh-controls {
            display: flex;
            gap: 8px;
        }

        .nh-minimize, .nh-close {
            width: 24px;
            height: 24px;
            border-radius: 50%;
            background: transparent;
            color: #666;
            border: 1px solid #ddd;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            font-size: 16px;
            transition: all 0.2s;
        }

        .nh-minimize:hover, .nh-close:active {
            background: #f0f0f0;
            color: #222;
        }

        .nh-body {
            padding: 20px;
            overflow-y: auto;
            flex-grow: 1;
            display: flex;
            flex-direction: column;
            position: relative;
            z-index: 1;
        }

        .nh-input-group {
            margin-bottom: 18px;
        }

        .nh-input-group label {
            display: block;
            margin-bottom: 8px;
            font-size: 16px;
            color: #555;
            font-weight: 500;
        }

        .nh-input {
            width: 100%;
            padding: 12px;
            border: 1px solid #ddd;
            border-radius: 6px;
            font-size: 16px;
            box-sizing: border-box;
            background: #fafafa;
            color: #333;
        }

        .nh-input:focus {
            border-color: #4a90e2;
            outline: none;
            background: #fff;
            box-shadow: 0 0 0 2px rgba(74, 144, 226, 0.1);
        }

        .nh-detect-btn {
            background: #f0f0f0;
            border: 1px solid #ddd;
            border-radius: 6px;
            padding: 12px;
            font-size: 15px;
            margin-top: 8px;
            cursor: pointer;
            transition: background 0.2s;
            color: #444;
            width: 100%;
        }

        .nh-detect-btn:active {
            background: #e6e6e6;
        }

        .nh-btn-group {
            display: flex;
            flex-direction: column;
            gap: 10px;
            margin-top: auto;
            margin-top: 15px;
        }

        .nh-primary-btn {
            flex: 1;
            background: #4a90e2;
            color: white;
            border: none;
            border-radius: 6px;
            padding: 15px 0;
            font-size: 16px;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.2s;
        }

        .nh-primary-btn:active {
            background: #3a7bc8;
        }

        .nh-primary-btn:disabled {
            background: #c5d9f7;
            cursor: not-allowed;
        }

        .nh-secondary-btn {
            width: 100%;
            flex: 1;
            background: #f0f0f0;
            color: #666;
            border: 1px solid #ddd;
            border-radius: 6px;
            padding: 15px 0;
            font-size: 16px;
            cursor: pointer;
            transition: all 0.2s;
        }

        .nh-secondary-btn:active {
            background: #e6e6e6;
            border-color: #ccc;
        }

        .nh-progress-bar {
            height: 6px;
            background: #f0f0f0;
            border-radius: 3px;
            overflow: hidden;
            margin-top: 15px;
        }

        .nh-progress-fill {
            height: 100%;
            background: #4a90e2;
            border-radius: 3px;
            width: 0%;
            transition: width 0.5s ease;
        }

        .nh-counter {
            text-align: center;
            font-size: 15px;
            color: #666;
            margin-top: 8px;
        }

        .nh-message-box {
            position: absolute;
            bottom: 0;
            left: 0;
            right: 0;
            padding: 4px 15px;
            border-top: 1px solid #eee;
            text-align: center;
            display: none;
            font-size: 14px;
            background: #f9f9f9;
            z-index: 10;
        }

        .message-info {
            color: #1e6bb8;
            background: #dff3ff;
        }

        .message-success {
            color: #2a7a2c;
            background: #e0f5e0;
        }

        .message-error {
            color: #c00;
            background: #ffebeb;
        }

        .nh-resume-section {
            margin-bottom: 18px;
            padding-bottom: 15px;
            border-bottom: 1px solid #f0f0f0;
        }

        .nh-resume-section label {
            display: flex;
            align-items: center;
            cursor: pointer;
            font-size: 16px;
            color: #555;
            font-weight: 500;
            margin-bottom: 0;
        }

        .nh-resume-info {
            max-height: 200px;
            overflow-y: auto;
            background: #f9f9f9;
            border-radius: 6px;
            padding: 15px;
            margin-top: 10px;
            font-size: 14px;
            border: 1px dashed #eee;
        }

        .resume-file-info {
            margin-bottom: 10px;
            font-size: 14px;
            line-height: 1.5;
            color: #555;
        }

        .resume-file-info p {
            margin: 8px 0;
            overflow: hidden;
            text-overflow: ellipsis;
            font-size: 14px;
        }

        .url-display {
            display: inline-block;
            max-width: 100%;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            vertical-align: bottom;
            font-family: monospace;
            color: #4a90e2;
        }

        /* 高亮删除线样式 */
        .strike-highlight {
            text-decoration: line-through;
            color: #e53935;
            background-color: rgba(229, 57, 53, 0.1);
            border-radius: 2px;
            padding: 0 2px;
        }

        /* 预览窗口样式 */
        .nh-preview-window {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: 10002;
            background: #ffffff;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            overflow: hidden;
            display: flex;
            flex-direction: column;
        }

        .nh-preview-container {
            display: flex;
            flex-direction: column;
            height: 100%;
        }

        .nh-preview-header {
            padding: 18px 20px;
            background: #f8f8f8;
            border-bottom: 1px solid #eee;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .nh-preview-title {
            font-weight: 600;
            font-size: 17px;
            color: #333;
        }

        .nh-preview-body {
            display: flex;
            flex: 1;
            overflow: hidden;
            flex-direction: column;
        }

        .nh-preview-content {
            flex: 1;
            padding: 15px;
            overflow: hidden;
            display: flex;
            flex-direction: column;
        }

        .nh-chapter-preview {
            width: 100%;
            flex: 1;
            border: 1px solid #eaeaea;
            border-radius: 8px;
            padding: 15px;
            font-size: 16px;
            line-height: 1.6;
            background: #fcfcfc;
            color: #333;
            overflow-y: auto;
            box-sizing: border-box;
            white-space: pre-wrap;
        }

        .nh-filter-section {
            flex: 1;
            display: flex;
            flex-direction: column;
            border-top: 1px solid #eee;
            padding: 15px;
        }

        .nh-filter-header {
            display: flex;
            align-items: center;
            margin-bottom: 15px;
        }

        .nh-add-filter-btn {
            width: 28px;
            height: 28px;
            border-radius: 50%;
            background: #f0f0f0;
            color: #444;
            border: 1px solid #ddd;
            font-size: 18px;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            margin-right: 10px;
            transition: background 0.2s;
        }

        .nh-add-filter-btn:active {
            background: #e6e6e6;
        }

        .nh-filters-container {
            flex: 3 !important;
            overflow-y: auto;
            border: 1px solid #eee;
            border-radius: 8px;
            padding: 10px;
            margin-bottom: 15px;
        }

        .nh-filter-item {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
        }

        .nh-filter-item input {
            flex: 1;
            padding: 12px;
            border: 1px solid #ddd;
            border-radius: 6px;
            background: #fafafa;
            color: #333;
            font-size: 16px;
        }

        .nh-remove-filter-btn {
            width: 28px;
            height: 28px;
            border-radius: 0 6px 6px 0;
            background: #f0f0f0;
            color: #444;
            border: none;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            font-size: 18px;
            transition: all 0.2s;
            border: 1px solid #ddd;
        }

        .nh-remove-filter-btn:active {
            background: #e6e6e6;
        }

        .nh-filter-footer {
            flex: 1;
            border-top: 1px solid #eee;
            padding-top: 15px;
            box-sizing: border-box;
        }

        .nh-filter-footer button {
            width: 100%;
            padding: 15px 0;
            font-size: 16px;
            font-weight: 500;
            border-radius: 6px;
            cursor: pointer;
            transition: all 0.2s;
        }

        .strike-highlight {
            text-decoration: line-through;
            color: #e53935;
            background-color: rgba(229, 57, 53, 0.1);
            border-radius: 2px;
            padding: 0 2px;
        }

        /* 下一页按钮样式 */
        .nh-next-btn {
            width: 100%;
            padding: 15px 0;
            font-size: 16px;
            font-weight: 500;
            border-radius: 6px;
            background: #ffffff;
            color: #4a90e2;
            border: 1px solid #4a90e2;
            cursor: pointer;
            transition: all 0.2s;
            margin-bottom: 10px;
        }

        .nh-next-btn:active {
            background: #f0f7ff;
            border-color: #3a7bc8;
        }

        .nh-next-btn:disabled {
            background: #f5f5f5;
            color: #999;
            border-color: #ddd;
            cursor: not-allowed;
        }

        /* 动画效果 */
        @keyframes nh-fadeIn {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }

        @keyframes nh-fadeOut {
            from { opacity: 1; transform: translateY(0); }
            to { opacity: 0; transform: translateY(10px); }
        }

        /* 横屏优化 */
        @media (orientation: landscape) {
            .nh-preview-body {
                flex-direction: row;
            }

            .nh-preview-content {
                flex: 1;
            }

            .nh-filter-section {
                flex: 1;
                border-top: none;
                border-left: 1px solid #eee;
            }
        }
    `;

    // 辅助函数：生成更精确的选择器
    function generateSelector(element) {
        if (!element) return null;

        // 优先使用ID
        if (element.id) return `#${element.id}`;

        // 尝试使用类名和标签名组合
        if (element.className && typeof element.className === 'string') {
            const classes = element.className.trim().split(/\s+/)
                .filter(cls => !/^(ng-|js-|active|selected|hidden)/.test(cls));

            if (classes.length > 0) {
                // 尝试添加父元素信息以增加特异性
                let selector = `${element.tagName.toLowerCase()}.${classes.join('.')}`;

                // 检查选择器是否唯一
                if (document.querySelectorAll(selector).length === 1) {
                    return selector;
                }

                // 如果不唯一，添加父元素信息
                if (element.parentElement) {
                    const parentSelector = generateSelector(element.parentElement);
                    if (parentSelector) {
                        return `${parentSelector} > ${element.tagName.toLowerCase()}.${classes.join('.')}`;
                    }
                }
            }
        }

        // 使用标签名+索引作为备选
        const tagName = element.tagName.toLowerCase();
        const parent = element.parentElement;
        if (parent) {
            const siblings = Array.from(parent.children).filter(el => el.tagName === element.tagName);
            const index = siblings.indexOf(element) + 1;

            if (siblings.length > 1) {
                return `${tagName}:nth-of-type(${index})`;
            }
        }

        return tagName;
    }

    // 规范化文本：移除多余空格和换行
    function normalizeText(text) {
        return text.replace(/\s+/g, ' ').trim();
    }

    // 查找包含特定文本的最内层元素（改进版）
    function findInnermostElement(root, text) {
        const normalizedText = normalizeText(text);
        if (!root || !normalizedText || normalizedText === '') return null;

        let deepestElement = null;
        let deepestLevel = -1;
        let bestMatchScore = -1;

        // 使用TreeWalker进行高效DOM遍历
        const treeWalker = document.createTreeWalker(
            root,
            NodeFilter.SHOW_ELEMENT,
            {
                acceptNode: function(node) {
                    // 只考虑可见元素
                    const style = window.getComputedStyle(node);
                    if (style.display === 'none' || style.visibility === 'hidden') {
                        return NodeFilter.FILTER_SKIP;
                    }

                    // 检查文本是否匹配（使用规范化文本）
                    const elementText = normalizeText(node.textContent);
                    if (elementText.includes(normalizedText)) {
                        return NodeFilter.FILTER_ACCEPT;
                    }
                    return NodeFilter.FILTER_SKIP;
                }
            }
        );

        while(treeWalker.nextNode()) {
            const node = treeWalker.currentNode;
            let level = 0;
            let parent = node.parentElement;

            // 计算嵌套层级
            while (parent && parent !== root) {
                level++;
                parent = parent.parentElement;
            }

            // 计算匹配分数（文本相似度）- 使用规范化文本
            const elementText = normalizeText(node.textContent);
            const textMatchScore = calculateTextMatch(elementText, normalizedText);

            // 优先选择更深层级和更高匹配度的元素
            if (level > deepestLevel ||
               (level === deepestLevel && textMatchScore > bestMatchScore)) {
                deepestLevel = level;
                bestMatchScore = textMatchScore;
                deepestElement = node;
            }
        }

        return deepestElement;
    }

    // 计算文本匹配度（使用规范化文本）
    function calculateTextMatch(elementText, targetText) {
        elementText = normalizeText(elementText);
        targetText = normalizeText(targetText);

        // 完全匹配得最高分
        if (elementText === targetText) return 100;

        // 计算文本相似度
        let matchScore = 0;
        const targetWords = targetText.split(/\s+/);
        const elementWords = elementText.split(/\s+/);

        for (const word of targetWords) {
            if (elementText.includes(word)) {
                matchScore += word.length;
            }
        }

        return matchScore;
    }

    // 获取元素内的文本内容（完全保留原始格式）
    function getElementText(element) {
        if (!element) return '';

        // 特殊处理：移除广告元素
        const clone = element.cloneNode(true);
        const adSelectors = [
            '.ad', '.ads', '.advertisement',
            '.ad-container', '.google-ad',
            '.adsbygoogle', '.adsense',
            '.ad-unit', '.ad-wrapper'
        ];

        adSelectors.forEach(selector => {
            const ads = clone.querySelectorAll(selector);
            ads.forEach(ad => ad.remove());
        });

        // 将 <br> 系列标签统一转换为换行符
        const brElements = clone.querySelectorAll('br');
        brElements.forEach(br => {
            br.replaceWith('\n');
        });

        // 直接返回原始文本内容，不做任何修剪
        return clone.textContent;
    }

    // 修复后的 applyFilters 函数
    function applyFilters(content) {
      if (!state.filters.length) return content;

      const filters = state.filters.map(filter => {
        // 使用与高亮相同的转义逻辑
        const escaped = escapeRegExp(filter);
        const pattern = escaped.replace(/\s+/g, '\\s*');
        return new RegExp(pattern, 'g');
      });

      // 应用所有过滤器
      filters.forEach(regex => {
        content = content.replace(regex, '');
      });

      return content;
    }

    // 获取下一章链接元素
    function getNextChapterLink(root, linkTexts = ["下一章", "下一页", "下一节"]) {
        // 先尝试通过常见选择器查找
        const commonSelectors = [
            '.next', '.next-chapter', '.nextpage',
            '.bottom-chapter-next', '.post-next',
            '#next', '#nextChapter', '#nextpage'
        ];

        for (const selector of commonSelectors) {
            const link = root.querySelector(selector);
            if (link && link.href) return link;
        }

        // 尝试通过文本查找（使用规范化文本）
        const normalizedLinkTexts = linkTexts.map(normalizeText);
        for (const text of normalizedLinkTexts) {
            const element = findInnermostElement(root, text);
            if (element && element.href) return element;
        }

        // 最后尝试<a>标签中的文字
        const links = root.querySelectorAll('a');
        for (const link of links) {
            const linkText = normalizeText(link.textContent);
            if (normalizedLinkTexts.some(text => linkText.includes(text))) {
                return link;
            }
        }

        return null;
    }

    // 辅助函数：从元素数组中找出嵌套最深的元素
    function findDeepestElement(elements) {
        let deepestElement = elements[0];
        let maxDepth = 0;

        for (const element of elements) {
            let depth = 0;
            let parent = element.parentElement;

            while (parent) {
                depth++;
                parent = parent.parentElement;
            }

            if (depth > maxDepth) {
                maxDepth = depth;
                deepestElement = element;
            }
        }

        return deepestElement;
    }

    // 提取当前章节内容（完全保留原始格式）
    function extractChapterContent(root, titleSelector, contentSelector) {
        let title = "";
        let content = "";

        // ============== 标题提取逻辑修改 ==============
        const userProvidedTitleSelector = titleSelector &&
                                        titleSelector !== '未检测（自动识别）' &&
                                        titleSelector !== '未找到';

        // 优先使用用户提供的标题选择器
        if (userProvidedTitleSelector) {
            try {
                const titleElement = root.querySelector(titleSelector);
                if (titleElement) {
                    title = getElementText(titleElement);
                } else {
                    console.warn('使用自定义标题选择器但未找到元素:', titleSelector);
                }
            } catch (e) {
                console.error('标题选择器错误:', e);
            }
        }

        // 当用户未提供标题选择器时，智能查找标题
        if ((!title || title.length < 3) && !userProvidedTitleSelector) {
            const titleCandidates = [
                ...root.querySelectorAll('h1, h2, h3, h4')
            ].filter(h => {
                const txt = h.textContent;
                return txt.length > 5 &&
                       !txt.includes('菜单') &&
                       !txt.includes('导航') &&
                       !txt.includes('搜索');
            });

            if (titleCandidates.length > 0) {
                const chapterTitle = titleCandidates.find(h =>
                    /第[零一二三四五六七八九十百千\d]+章/.test(h.textContent)
                );
                title = chapterTitle ? getElementText(chapterTitle) :
                       getElementText(titleCandidates[0]);
            }
        }
        // ============== 内容提取逻辑修改 ==============
        const userProvidedContentSelector = contentSelector &&
                                          contentSelector !== '未检测（自动识别）' &&
                                          contentSelector !== '未找到';

        let contentElement = null;

        // 优先使用用户提供的内容选择器
        if (userProvidedContentSelector) {
            try {
                // 获取所有匹配选择器的元素
                const contentElements = root.querySelectorAll(contentSelector);

                if (contentElements.length > 0) {
                    // 选择包含文本内容的元素
                    const contentElementsWithText = [...contentElements].filter(el => {
                        const txt = el.textContent;
                        return txt.length > config.minChapterLength &&
                               txt.includes("。") &&
                               txt.includes("，");
                    });

                    if (contentElementsWithText.length > 0) {
                        // 选择嵌套最深的元素（通常是主要内容）
                        contentElement = findDeepestElement(contentElementsWithText);
                    } else {
                        // 即使没找到带标点的内容，也使用第一个匹配元素
                        contentElement = contentElements[0];
                        console.warn('自定义选择器找到的元素可能不包含完整内容');
                    }
                }

                if (contentElement) {
                    content = getElementText(contentElement);
                }
            } catch (e) {
                console.error('内容选择器错误:', e);
            }
        }

        // 当用户未提供选择器或选择器找不到内容时，进行智能查找
        if (!content || content.length < config.minChapterLength) {
            console.log(userProvidedContentSelector
                ? '自定义选择器提取内容过短，尝试智能识别'
                : '智能识别内容元素');

            const contentCandidates = [
                ...root.querySelectorAll('div, section, article, p')
            ].filter(div => {
                const txt = div.textContent;
                return txt.length > config.minChapterLength &&
                       txt.includes("。") &&
                       txt.includes("，") &&
                       !txt.includes('广告') &&
                       !txt.includes('推荐');
            });

            if (contentCandidates.length > 0) {
                // 使用智能方式获取内容（保留原始格式）
                content = contentCandidates.reduce((longest, div) => {
                    const current = getElementText(div);
                    return current.length > longest.length ? current : longest;
                }, "");
            }
        }

        return {
            title: title || "未知章节",
            content: content || ""
        };
    }

    // 转义正则特殊字符
    function escapeRegExp(string) {
        return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    }

    // HTML转义函数
    function escapeHtml(html) {
        const div = document.createElement('div');
        div.textContent = html;
        return div.innerHTML;
    }

    // 获取新页面的DOM
    async function fetchPage(url) {
        if (state.cancelRequested) return null;

        try {
            const response = await new Promise((resolve, reject) => {
                const timeout = setTimeout(() => {
                    reject(new Error('请求超时'));
                }, config.defaultTimeout);

                GM_xmlhttpRequest({
                    method: 'GET',
                    url: url,
                    responseType: 'document',
                    onload: (rsp) => {
                        clearTimeout(timeout);
                        resolve(rsp);
                    },
                    onerror: (err) => {
                        clearTimeout(timeout);
                        reject(err);
                }
                });
            });

            const html = response.responseText;
            const parser = new DOMParser();
            return parser.parseFromString(html, 'text/html');
        } catch (error) {
            console.error('获取页面时出错:', error.message);
            return null;
        }
    }

    // 处理小说内容提取过程
    async function processContent(startUrl, titleSelector, contentSelector) {
        state.isProcessing = true;
        state.chaptersExtracted = 0;
        state.cancelRequested = false;

        if (!state.isResuming) {
            state.extractedContent = "";
            state.lastChapterUrl = startUrl;
        } else {
            state.extractedContent = state.resumeContent;
            state.lastChapterUrl = state.resumeUrl;
            state.chaptersExtracted = state.resumeChapters || 0;
            state.isResuming = false;
        }

        let currentUrl = state.lastChapterUrl;
        let retryCount = 0;
        let samePageCount = 0;
        let lastPageText = "";

        while (!state.cancelRequested && state.chaptersExtracted < config.maxChapters) {
            // 获取页面DOM
            const currentDom = await fetchPage(currentUrl);
            if (!currentDom) {
                if (retryCount++ < state.maxRetries) continue;
                break;
            }

            // 提取章节内容
            const chapter = extractChapterContent(currentDom, titleSelector, contentSelector);
            if (!chapter.content || chapter.content.length < config.minChapterLength) {
                console.log('章节内容过短，跳过:', chapter.title);
                break;
            }

            // 检测重复页面 (防止无限循环)
            if (lastPageText === chapter.content.substring(0, 200)) {
                samePageCount++;
                if (samePageCount > 2) break; // 连续相同页面过多
            } else {
                samePageCount = 0;
            }
            lastPageText = chapter.content.substring(0, 200);

            // 在此处应用过滤条件
            let filteredContent = `\n\n${chapter.title}\n\n${chapter.content}\n`;
            if (state.filters.length > 0) {
              filteredContent = applyFilters(filteredContent);
            }

            // 添加到提取内容
            state.extractedContent += filteredContent;
            state.chaptersExtracted++;

            // 更新进度
            updateProgress();

            // 获取下一章链接
            const nextLink = getNextChapterLink(currentDom);
            if (!nextLink || !nextLink.href) {
                console.log('未找到下一章链接');
                break;
            }

            // 转换为完整URL
            let nextUrl = nextLink.href;
            if (!nextUrl.startsWith('http')) {
                const base = new URL(currentUrl);
                nextUrl = new URL(nextUrl, base.origin).href;
            }

            // 更新最后章节URL
            state.lastChapterUrl = nextUrl;
            currentUrl = nextUrl;

            // 添加延迟防止请求过快
            await new Promise(resolve => setTimeout(resolve, 300));
        }

        state.isProcessing = false;
        return state.extractedContent;
    }

    // 更新UI进度
    function updateProgress() {
        const progressEl = state.shadowRoot.querySelector('#progressBar');
        const counterEl = state.shadowRoot.querySelector('#chapterCounter');

        if (progressEl && counterEl) {
            const percentage = Math.min(100, Math.round(
                (state.chaptersExtracted / config.maxChapters) * 100
            ));

            progressEl.style.width = `${percentage}%`;
            counterEl.textContent = `已提取 ${state.chaptersExtracted} 章`;
        }
    }

    // 下载文本内容（添加元数据）
    function downloadContentAsFile(text, fileName) {
        try {
            // 获取当前使用的选择器
            const titleSelector = state.shadowRoot.querySelector('#detectedTitleSelector').textContent;
            const contentSelector = state.shadowRoot.querySelector('#detectedContentSelector').textContent;
            // 添加元数据到文件末尾
            const metadata = {
                lastChapterUrl: state.lastChapterUrl,
                chaptersExtracted: state.chaptersExtracted,
                startUrl: window.location.href,
                timestamp: new Date().toISOString(),
                version: "3.3.0-mobile",
                titleSelector: titleSelector,
                contentSelector: contentSelector,
                filters: state.filters // 保存过滤条件
            };

            const metadataStr = `${METADATA_MARKER}${JSON.stringify(metadata)}${METADATA_END}`;
            const fullContent = text + '\n\n' + metadataStr;

            // 创建Blob对象
            const blob = new Blob([fullContent], {type: 'text/plain;charset=utf-8'});

            // 生成文件URL
            const url = URL.createObjectURL(blob);

            // 创建下载链接并触发下载
            const link = document.createElement('a');
            link.href = url;
            link.download = fileName + '.txt';
            document.body.appendChild(link);
            link.click();

            // 清理
            setTimeout(() => {
                document.body.removeChild(link);
                URL.revokeObjectURL(url);
            }, 100);

            return true;
        } catch (error) {
            console.error('下载失败:', error);
            showMessage('文件下载失败，请重试！', 'error');
            return false;
        }
    }

    // 解析元数据
    function parseMetadata(content) {
        const markerIndex = content.lastIndexOf(METADATA_MARKER);
        if (markerIndex === -1) return null;

        const endIndex = content.indexOf(METADATA_END, markerIndex);
        if (endIndex === -1) return null;

        try {
            const jsonStr = content.substring(
                markerIndex + METADATA_MARKER.length,
                endIndex
            );
            return JSON.parse(jsonStr);
        } catch (e) {
            console.error('解析元数据失败', e);
            return null;
        }
    }

    // 修改 showMessage 函数
    function showMessage(message, type = 'info') {
        const messageEl = state.shadowRoot.querySelector('#messageBox');
        if (!messageEl) return;

        messageEl.textContent = message;
        messageEl.className = `nh-message-box message-${type}`;
        messageEl.style.display = 'block';

        // 添加动画效果
        messageEl.style.animation = 'nh-fadeIn 0.3s ease-in-out';

        // 修复位置问题：始终确保消息框在悬浮窗底部
        const uiContainer = state.shadowRoot.querySelector('#novelHelperUI');
        if (uiContainer) {
            // 计算悬浮窗底部位置
            const rect = uiContainer.getBoundingClientRect();
            messageEl.style.bottom = '0';
            messageEl.style.left = '0';
            messageEl.style.right = '0';
        }

        setTimeout(() => {
            messageEl.style.animation = 'nh-fadeOut 0.3s ease-in-out';
            setTimeout(() => {
                messageEl.style.display = 'none';
            }, 200);
        }, 3000);
    }

    // 修改函数：清理过滤文本（增强处理能力）
    function cleanFilterText(text) {
        // 去除HTML标签
        let cleaned = text.replace(/<[^>]+>/g, '');
        // 处理HTML实体
        cleaned = cleaned.replace(/&nbsp;|&#160;/g, ' ');
        // 处理全角空格
        cleaned = cleaned.replace(/　/g, ' ');
        // 处理换行符 - 替换为空格
        cleaned = cleaned.replace(/\r\n|\r|\n/g, ' ');
        // 去除连续多个空格
        cleaned = cleaned.replace(/\s+/g, ' ');
        return cleaned.trim();
    }

    // 修改函数：处理文件上传（添加文本清理）
    function handleFileUpload(event) {
        const file = event.target.files[0];
        if (!file) return;

        const reader = new FileReader();
        reader.onload = function(e) {
            const content = e.target.result;
            const metadata = parseMetadata(content);

            if (metadata) {
                // 移除元数据部分获取纯文本内容
                const pureContent = content.substring(0, content.lastIndexOf(METADATA_MARKER));

                // 设置恢复状态
                state.isResuming = true;
                state.resumeContent = pureContent;
                state.resumeUrl = metadata.lastChapterUrl;
                state.resumeChapters = metadata.chaptersExtracted;

                // 恢复过滤条件 - 增加清理处理
                if (metadata.filters && metadata.filters.length > 0) {
                    // 对每个过滤条件执行清理
                    state.filters = metadata.filters.map(filter => cleanFilterText(filter));
                }

                // 处理长URL显示
                const maxUrlLength = 40;
                let displayUrl = metadata.lastChapterUrl;
                if (displayUrl.length > maxUrlLength) {
                    const start = displayUrl.substring(0, 15);
                    const end = displayUrl.substring(displayUrl.length - 15);
                    displayUrl = `${start}...${end}`;
                }

                // 恢复选择器信息
                if (metadata.titleSelector && metadata.contentSelector) {
                    state.shadowRoot.querySelector('#detectedTitleSelector').textContent = metadata.titleSelector;
                    state.shadowRoot.querySelector('#detectedContentSelector').textContent = metadata.contentSelector;
                    state.shadowRoot.querySelector('#detectionResults').style.display = 'block';

                    // 更新状态中的选择器
                    state.titleSelector = metadata.titleSelector;
                    state.contentSelector = metadata.contentSelector;
                }

                // 更新UI显示恢复信息 - 增加选择器显示
                state.shadowRoot.querySelector('#resumeInfo').innerHTML = `
                    <div class="resume-file-info">
                        <p>检测到可继续下载的文件：<br><strong>${file.name}</strong></p>
                        <p>已下载章节: <strong>${metadata.chaptersExtracted}</strong></p>
                        <p>最后章节URL: <span class="url-display" title="${metadata.lastChapterUrl}">${displayUrl}</span></p>
                        <!-- 新增选择器信息 -->
                        <p>标题选择器: <code>${metadata.titleSelector || '未保存'}</code></p>
                        <p>内容选择器: <code>${metadata.contentSelector || '未保存'}</code></p>
                        <!-- 过滤条件 -->
                        ${metadata.filters && metadata.filters.length > 0 ?
                            `<p>过滤条件: <code>${metadata.filters.map(f => f.replace(/</g, '&lt;')).join('</code>, <code>')}</code></p>` : ''}
                    </div>
                `;

                // 更新按钮状态 - 启用开始提取按钮
                state.shadowRoot.querySelector('#nhStartBtn').disabled = false;
            } else {
                showMessage('未找到可继续下载的元数据', 'error');
                // 清除无效的上传信息
                state.shadowRoot.querySelector('#resumeInfo').innerHTML = '　　请选择之前下载的文件继续下载';
                // 禁用开始提取按钮
                state.shadowRoot.querySelector('#nhStartBtn').disabled = true;
            }
        };
        reader.readAsText(file);
    }

    // 应用高亮效果（匹配过滤文本）
    function applyHighlight(content, filters) {
        if (!filters.length) return escapeHtml(content);

        // 创建匹配范围数组
        const ranges = [];

        filters.forEach(filter => {
            // 忽略空过滤器
            if (!filter.trim()) return;

            try {
                // 创建正则表达式（支持跨行匹配）
                const escapedFilter = escapeRegExp(filter).replace(/\s+/g, '\\s*');
                const regex = new RegExp(escapedFilter, 'g');

                let match;
                while ((match = regex.exec(content)) !== null) {
                    // 确保不会匹配到metadata部分
                    if (!match[0].includes(METADATA_MARKER)) {
                        ranges.push({
                            start: match.index,
                            end: match.index + match[0].length
                        });
                    }
                }
            } catch (e) {
                console.error('高亮处理错误:', e);
            }
        });

        // 合并重叠的范围
        ranges.sort((a, b) => a.start - b.start);

        const mergedRanges = [];
        let currentRange = ranges[0];

        if (currentRange) {
            for (let i = 1; i < ranges.length; i++) {
                const nextRange = ranges[i];
                if (nextRange.start <= currentRange.end) {
                    currentRange.end = Math.max(currentRange.end, nextRange.end);
                } else {
                    mergedRanges.push(currentRange);
                    currentRange = nextRange;
                }
            }
            mergedRanges.push(currentRange);
        }

        // 如果没有匹配范围，返回原始转义内容
        if (mergedRanges.length === 0) return escapeHtml(content);

        // 构建带有高亮的HTML
        let highlightedContent = '';
        let lastIndex = 0;

        mergedRanges.forEach(range => {
            // 添加范围前的内容
            if (range.start > lastIndex) {
                highlightedContent += escapeHtml(content.substring(lastIndex, range.start));
            }

            // 添加高亮范围
            const matchedText = escapeHtml(content.substring(range.start, range.end));
            highlightedContent += `<span class="strike-highlight">${matchedText}</span>`;

            lastIndex = range.end;
        });

        // 添加剩余内容
        if (lastIndex < content.length) {
            highlightedContent += escapeHtml(content.substring(lastIndex));
        }

        return highlightedContent;
    }
    // UI界面管理
    function createUI() {
        // 创建Shadow Host
        const shadowRoot = createShadowHost();
        state.shadowRoot = shadowRoot;

        // 添加样式到Shadow DOM
        addStylesToShadow(shadowRoot, UI_STYLES);

        // 创建UI容器
        const uiContainer = document.createElement('div');
        uiContainer.id = 'novelHelperUI';
        uiContainer.className = 'novel-helper-ui persistent-floating-window';
        shadowRoot.appendChild(uiContainer);

        // 创建UI内容
        uiContainer.innerHTML = `
            <div class="nh-container">
                <div class="nh-header" id="dragHandle">
                    <span class="nh-title">小说小助手 v3.3（手机版）</span>
                    <div class="nh-controls">
                        <button id="nhMinimize" class="nh-minimize">−</button>
                        <button id="nhClose" class="nh-close">×</button>
                    </div>
                </div>

                <div class="nh-body" id="nhMainContent">
                    <!-- 断点续传部分 -->
                    <div class="nh-resume-section" id="resumeSection">
                        <label>
                            <input type="checkbox" id="resumeCheckbox"> 断点续传
                        </label>
                        <div id="resumeFileSection" style="display:none; margin-top:10px;">
                            <input type="file" id="resumeFileUpload" accept=".txt" style="display:none">
                            <button id="selectResumeFile" class="nh-secondary-btn">选择已下载文件</button>
                            <div id="resumeInfo" class="nh-resume-info">　　请选择之前下载的文件继续下载</div>
                        </div>
                    </div>

                    <!-- 配置部分 -->
                    <div id="configSection">
                        <div class="nh-input-group">
                            <label>章节标题示例</label>
                            <input type="text" id="titleExample" class="nh-input" placeholder="在此粘贴章节标题的文本">
                            <button id="detectTitleBtn" class="nh-detect-btn">检测</button>
                        </div>

                        <div class="nh-input-group">
                            <label>内容示例</label>
                            <input type="text" id="contentExample" class="nh-input" placeholder="在此粘贴小说内容的文本">
                            <button id="detectContentBtn" class="nh-detect-btn">检测</button>
                        </div>

                        <div id="detectionResults" style="display:none; margin:10px 0;">
                            <p>标题选择器: <span id="detectedTitleSelector">未检测（自动识别）</span></p>
                            <p>内容选择器: <span id="detectedContentSelector">未检测（自动识别）</span></p>
                        </div>
                    </div>

                    <!-- 预览选项 -->
                    <div class="nh-input-group" id="previewOption">
                        <label>
                            <input type="checkbox" id="previewCheckbox"> 首章预览
                        </label>
                    </div>

                    <div class="nh-btn-group">
                        <button id="nhStartBtn" class="nh-primary-btn">开始提取</button>
                        <button id="nhStopBtn" class="nh-secondary-btn" style="display:none">停止</button>
                    </div>

                    <div id="progressSection" style="display:none; margin-top:15px;">
                        <div class="nh-progress-bar">
                            <div id="progressBar" class="nh-progress-fill"></div>
                        </div>
                        <div id="chapterCounter" class="nh-counter">准备中...</div>
                    </div>

                    <!-- 下载部分 -->
                    <div id="downloadSection" style="display:none; text-align:center;">
                        <div class="nh-input-group">
                            <label>保存文件名</label>
                            <input type="text" id="fileNameInput" class="nh-input" value="新小说">
                        </div>
                        <div class="nh-btn-group">
                            <button id="nhDownloadBtn" class="nh-primary-btn">下载小说</button>
                            <button id="nhNewExtractBtn" class="nh-secondary-btn">提取其他</button>
                        </div>
                    </div>
                </div>

                <div id="messageBox" class="nh-message-box"></div>
            </div>
        `;

        // 确保UI元素已经存在后再绑定事件
        setTimeout(() => {
            setupEventListeners(uiContainer, shadowRoot);
        }, 100);

        // 初始化拖拽功能（移动端）
        setupMobileDragging(uiContainer);

        return uiContainer;
    }

    // 移动端拖拽实现
    function setupMobileDragging(uiContainer) {
        let startY, startTop;
        const dragHandle = uiContainer.querySelector('#dragHandle');

        dragHandle.addEventListener('touchstart', function(e) {
            startY = e.touches[0].clientY;
            startTop = uiContainer.offsetTop;
            e.preventDefault();
        }, { passive: false });

        document.addEventListener('touchmove', function(e) {
            if (startY === undefined) return;
            const currentY = e.touches[0].clientY;
            const diffY = currentY - startY;
            const newTop = startTop + diffY;

            // 限制在屏幕范围内
            const maxTop = window.innerHeight - 100;
            uiContainer.style.top = `${Math.max(50, Math.min(maxTop, newTop))}px`;
            e.preventDefault();
        }, { passive: false });

        document.addEventListener('touchend', function() {
            startY = undefined;
        });
    }

    // 创建预览窗口（使用Shadow DOM）
    function createPreviewWindow(firstChapter, isResumePreview = false) {
        const previewTitle = isResumePreview ? "续传内容预览" : "预览";

        // 创建Shadow Host
        const shadowRoot = createShadowHost();
        state.previewShadowRoot = shadowRoot;

        // 添加样式到Shadow DOM
        addStylesToShadow(shadowRoot, UI_STYLES);

        // 创建预览容器
        const previewContainer = document.createElement('div');
        previewContainer.id = 'previewWindow';
        previewContainer.className = 'nh-preview-window';
        shadowRoot.appendChild(previewContainer);

        // 保存原始文本（用于高亮处理）
        let originalText = firstChapter.title + '\n\n' + firstChapter.content;

        previewContainer.innerHTML = `
            <div class="nh-preview-container">
                <div class="nh-preview-header">
                    <span class="nh-preview-title">${previewTitle}</span>
                    <button id="closePreviewBtn" class="nh-close">×</button>
                </div>
                <div class="nh-preview-body">
                    <div class="nh-preview-content">
                        <div id="chapterPreview" class="nh-chapter-preview"></div>
                    </div>
                    <div class="nh-filter-section">
                        <div class="nh-filter-header">
                            <button id="addFilterBtn" class="nh-add-filter-btn">+</button>
                            <span>添加过滤内容（从原文中删除）</span>
                        </div>
                        <div id="filtersContainer" class="nh-filters-container"></div>
                        <div class="nh-filter-footer">
                            <button id="nextChapterBtn" class="nh-next-btn">下一页</button>
                            <button id="startExtractBtn" class="nh-primary-btn">开始提取</button>
                        </div>
                    </div>
                </div>
            </div>
        `;

        // 应用高亮
        const chapterPreview = shadowRoot.querySelector('#chapterPreview');
        chapterPreview.innerHTML = applyHighlight(originalText, state.filters);

        // 当前预览状态
        let currentPreviewUrl = isResumePreview ? state.resumeUrl : window.location.href;
        let currentTitleSelector = state.titleSelector || state.shadowRoot.querySelector('#detectedTitleSelector').textContent;
        let currentContentSelector = state.contentSelector || state.shadowRoot.querySelector('#detectedContentSelector').textContent;

        // 实时高亮函数
        const updateHighlight = () => {
            // 收集过滤条件 - 增加清理处理
            const filterInputs = shadowRoot.querySelectorAll('.nh-filter-item input');
            const filters = [];
            filterInputs.forEach(input => {
                const cleanedFilter = cleanFilterText(input.value);
                if (cleanedFilter) {
                    filters.push(cleanedFilter);
                }
            });

            // 应用高亮
            chapterPreview.innerHTML = applyHighlight(originalText, filters);
        };

        // 事件监听
        shadowRoot.querySelector('#closePreviewBtn').addEventListener('click', () => {
            shadowRoot.host.remove();
        });

        shadowRoot.querySelector('#addFilterBtn').addEventListener('click', () => {
            addFilterItem(shadowRoot.querySelector('#filtersContainer'));
        });

        // 下一页按钮功能
        shadowRoot.querySelector('#nextChapterBtn').addEventListener('click', async () => {
            // 禁用按钮防止重复点击
            const nextBtn = shadowRoot.querySelector('#nextChapterBtn');
            nextBtn.disabled = true;
            nextBtn.textContent = '加载中...';

            try {
                // 获取当前页面的DOM
                const currentDom = await fetchPage(currentPreviewUrl);
                if (!currentDom) {
                    showMessage('获取页面失败', 'error');
                    return;
                }

                // 获取下一章链接
                const nextLink = getNextChapterLink(currentDom);
                if (!nextLink || !nextLink.href) {
                    showMessage('未找到下一章链接', 'info');
                    return;
                }

                // 转换为完整URL
                let nextUrl = nextLink.href;
                if (!nextUrl.startsWith('http')) {
                    const base = new URL(currentPreviewUrl);
                    nextUrl = new URL(nextUrl, base.origin).href;
                }

                // 更新当前预览URL
                currentPreviewUrl = nextUrl;

                // 获取下一章内容
                const nextDom = await fetchPage(nextUrl);
                if (!nextDom) {
                    showMessage('获取下一章失败', 'error');
                    return;
                }

                // 提取章节内容
                const nextChapter = extractChapterContent(nextDom, currentTitleSelector, currentContentSelector);
                if (!nextChapter.content || nextChapter.content.length < config.minChapterLength) {
                    showMessage('章节内容过短', 'warning');
                    return;
                }

                // 更新预览内容
                const newOriginalText = nextChapter.title + '\n\n' + nextChapter.content;
                originalText = newOriginalText;

                // 直接刷新红线（应用当前过滤条件）
                updateHighlight();

                // 滚动到顶部
                chapterPreview.scrollTop = 0;

            } catch (error) {
                console.error('获取下一章出错:', error);
                showMessage('获取下一章时出错', 'error');
            } finally {
                // 恢复按钮状态
                nextBtn.disabled = false;
                nextBtn.textContent = '下一页';
            }
        });

        // 开始提取按钮
        shadowRoot.querySelector('#startExtractBtn').addEventListener('click', async () => {
            // 收集过滤条件 - 增加清理处理
            const filterInputs = shadowRoot.querySelectorAll('.nh-filter-item input');
            state.filters = [];
            filterInputs.forEach(input => {
                const cleanedFilter = cleanFilterText(input.value);
                if (cleanedFilter) {
                    state.filters.push(cleanedFilter);
                }
            });

            // 隐藏主UI中的预览选项
            const previewCheckbox = state.shadowRoot.querySelector('#previewCheckbox');
            if (previewCheckbox) {
                previewCheckbox.closest('.nh-input-group').style.display = 'none';
            }

            // 关闭预览窗口
            shadowRoot.host.remove();

            // 开始提取
            await startExtraction(false);
        });

        // 添加过滤项函数
        function addFilterItem(container, value = '') {
            const div = document.createElement('div');
            div.className = 'nh-filter-item';
            div.innerHTML = `
                <input type="text" placeholder="输入要删除的内容" value="${escapeHtml(value)}">
                <button class="nh-remove-filter-btn">×</button>
            `;
            container.appendChild(div);

            const input = div.querySelector('input');
            const removeBtn = div.querySelector('.nh-remove-filter-btn');

            // 输入监听
            input.addEventListener('input', updateHighlight);

            // 移除按钮监听
            removeBtn.addEventListener('click', () => {
                div.remove();
                updateHighlight();
            });

            updateHighlight();
        }

        // 加载已有的过滤条件
        const filtersContainer = shadowRoot.querySelector('#filtersContainer');
        filtersContainer.innerHTML = '';

        if (state.filters && state.filters.length > 0) {
            state.filters.forEach(filter => {
                addFilterItem(filtersContainer, filter);
            });
        } else {
            // 添加一个空的
            addFilterItem(filtersContainer);
        }
    }

    // 事件监听器设置 - 修改为使用Shadow DOM内部的查找
    function setupEventListeners(uiContainer, shadowRoot) {

        // 断点续传复选框事件
        const resumeCheckbox = shadowRoot.querySelector('#resumeCheckbox');
        resumeCheckbox.addEventListener('change', function() {
            const isChecked = this.checked;
            shadowRoot.querySelector('#resumeFileSection').style.display = isChecked ? 'block' : 'none';
            shadowRoot.querySelector('#configSection').style.display = isChecked ? 'none' : 'block';

            // 重置状态变量
            shadowRoot.querySelector('#detectedTitleSelector').textContent = '未检测（自动识别）';
            shadowRoot.querySelector('#detectionResults').style.display = 'none';
            shadowRoot.querySelector('#detectedContentSelector').textContent = '未检测（自动识别）';
            shadowRoot.querySelector('#detectionResults').style.display = 'none';
            state.extractedContent = "";
            state.lastChapterUrl = "";
            state.isResuming = false;
            state.resumeContent = "";
            state.resumeUrl = "";
            state.resumeChapters = 0;
            state.filters = [];

            // 重置UI元素
            shadowRoot.querySelector('#resumeFileUpload').value = '';
            shadowRoot.querySelector('#resumeInfo').innerHTML = '　　请选择之前下载的文件继续下载';

            // 启用开始按钮（因为现在是非续传模式）
            shadowRoot.querySelector('#nhStartBtn').disabled = false;

            if (isChecked) {
                // 续传模式下，禁用开始按钮直到上传文件
                shadowRoot.querySelector('#nhStartBtn').disabled = true;
            }
        });

        // 检测按钮
        shadowRoot.querySelector('#detectTitleBtn').addEventListener('click', () => {
            const text = shadowRoot.querySelector('#titleExample').value.trim();
            if (text) {
                const element = findInnermostElement(document, text);
                const selector = generateSelector(element);
                shadowRoot.querySelector('#detectedTitleSelector').textContent = selector || '未找到';
                shadowRoot.querySelector('#detectionResults').style.display = 'block';
            }
        });

        shadowRoot.querySelector('#detectContentBtn').addEventListener('click', () => {
            const text = shadowRoot.querySelector('#contentExample').value.trim();
            if (text) {
                const element = findInnermostElement(document, text);
                const selector = generateSelector(element);
                shadowRoot.querySelector('#detectedContentSelector').textContent = selector || '未找到';
                shadowRoot.querySelector('#detectionResults').style.display = 'block';
            }
        });
        // 开始提取按钮
        shadowRoot.querySelector('#nhStartBtn').addEventListener('click', () => {
            startExtraction(true);
        });

        // 停止按钮
        shadowRoot.querySelector('#nhStopBtn').addEventListener('click', () => {
            state.cancelRequested = true;
            // 立即显示下载部分
            shadowRoot.querySelector('#progressSection').style.display = 'none';
            shadowRoot.querySelector('#nhStopBtn').style.display = 'none';
            shadowRoot.querySelector('#downloadSection').style.display = 'block';
            showMessage('正在停止，请稍等...', 'info');
        });

        // 下载按钮
        shadowRoot.querySelector('#nhDownloadBtn').addEventListener('click', () => {
            const filename = shadowRoot.querySelector('#fileNameInput').value.trim();
            downloadContentAsFile(state.extractedContent, filename);
            showMessage('下载成功！', 'success');
        });

        // 新提取按钮
        shadowRoot.querySelector('#nhNewExtractBtn').addEventListener('click', () => {
            shadowRoot.querySelector('#downloadSection').style.display = 'none';
            shadowRoot.querySelector('#configSection').style.display = 'block';
            shadowRoot.querySelector('#progressSection').style.display = 'none';
            shadowRoot.querySelector('#nhStartBtn').style.display = 'inline-block';
            shadowRoot.querySelector('#nhStopBtn').style.display = 'none';
            shadowRoot.querySelector('#resumeSection').style.display = 'block';
            shadowRoot.querySelector('#resumeCheckbox').checked = false;
            shadowRoot.querySelector('#resumeFileSection').style.display = 'none';
            // 显示预览选项
            shadowRoot.querySelector('#previewOption').style.display = 'block';

            // 重置状态
            shadowRoot.querySelector('#detectedTitleSelector').textContent = '未检测（自动识别）';
            shadowRoot.querySelector('#detectionResults').style.display = 'none';
            shadowRoot.querySelector('#detectedContentSelector').textContent = '未检测（自动识别）';
            shadowRoot.querySelector('#detectionResults').style.display = 'none';
            state.extractedContent = "";
            state.lastChapterUrl = "";
            state.isResuming = false;
            state.resumeContent = "";
            state.cancelRequested = false;
            state.isProcessing = false;
            state.filters = [];
        });

        // 关闭按钮
        shadowRoot.querySelector('#nhClose').addEventListener('click', () => {
            shadowRoot.host.remove();
        });

        // 最小化按钮
        shadowRoot.querySelector('#nhMinimize').addEventListener('click', () => {
            const body = shadowRoot.querySelector('#nhMainContent');
            const isVisible = body.style.display !== 'none';
            body.style.display = isVisible ? 'none' : 'block';
        });

        // 断点续传按钮
        shadowRoot.querySelector('#selectResumeFile').addEventListener('click', () => {
            shadowRoot.querySelector('#resumeFileUpload').click();
        });

        // 文件上传处理
        shadowRoot.querySelector('#resumeFileUpload').addEventListener('change', handleFileUpload);
    }

    async function startExtraction(checkPreview = true) {
        // 确保shadowRoot存在
        if (!state.shadowRoot) {
            console.error('startExtraction: shadowRoot is not available');
            showMessage('UI初始化失败，请刷新页面重试', 'error');
            return;
        }

        // 获取选择器
        let titleSelector, contentSelector;

        // 优先使用恢复的选择器
        if (state.isResuming && state.titleSelector && state.contentSelector) {
            titleSelector = state.titleSelector;
            contentSelector = state.contentSelector;
        }
        // 其次使用UI上的选择器
        else {
            const titleSelectorEl = state.shadowRoot.querySelector('#detectedTitleSelector');
            const contentSelectorEl = state.shadowRoot.querySelector('#detectedContentSelector');

            if (!titleSelectorEl || !contentSelectorEl) {
                console.error('选择器元素未找到');
                showMessage('UI元素缺失，请刷新页面重试', 'error');
                return;
            }

            titleSelector = titleSelectorEl.textContent;
            contentSelector = contentSelectorEl.textContent;

            // 保存到状态中
            state.titleSelector = titleSelector;
            state.contentSelector = contentSelector;
        }

        // 验证选择器
        if (!titleSelector || titleSelector === '未找到') {
            showMessage('请先检测标题选择器', 'error');
            return;
        }

        if (!contentSelector || contentSelector === '未找到') {
            showMessage('请先检测内容选择器', 'error');
            return;
        }

        // 检查是否预览
        if (checkPreview) {
            const previewCheckbox = state.shadowRoot.querySelector('#previewCheckbox');
            const isPreview = previewCheckbox && previewCheckbox.checked;

            if (isPreview) {
                // 获取预览的URL - 如果是续传模式使用下一章URL
                const previewUrl = state.isResuming ? state.resumeUrl : window.location.href;

                // 获取预览内容
                const firstChapter = await fetchFirstChapter(previewUrl, titleSelector, contentSelector);
                if (firstChapter && firstChapter.content) {
                    createPreviewWindow(firstChapter, state.isResuming);
                    return;
                } else {
                    showMessage('获取预览内容失败', 'error');
                }
            }
        }

        // 安全更新UI函数
        const safeUpdateUI = (selector, displayValue) => {
            const element = state.shadowRoot.querySelector(selector);
            if (element) {
                element.style.display = displayValue;
            } else {
                console.warn(`元素未找到: ${selector}`);
            }
        };

        // 批量安全更新UI
        safeUpdateUI('#resumeSection', 'none');
        safeUpdateUI('#previewOption', 'none');
        safeUpdateUI('#configSection', 'none');
        safeUpdateUI('#progressSection', 'block');
        safeUpdateUI('#nhStartBtn', 'none');
        safeUpdateUI('#nhStopBtn', 'inline-block');
        safeUpdateUI('#downloadSection', 'none');

        showMessage('开始提取小说内容...', 'info');

        // 开始提取
        const content = await processContent(
            state.isResuming ? state.resumeUrl : window.location.href,
            titleSelector,
            contentSelector
        );

        // 安全更新结果UI
        safeUpdateUI('#progressSection', 'none');
        safeUpdateUI('#nhStopBtn', 'none');
        safeUpdateUI('#downloadSection', 'block');

        if (state.cancelRequested) {
            showMessage('提取已停止', 'info');
        } else if (state.chaptersExtracted === 0) {
            showMessage('未提取到有效章节', 'error');
        } else {
            const chText = state.chaptersExtracted === 1 ? '章' : '章';
            showMessage(`成功提取 ${state.chaptersExtracted} ${chText} 内容！`, 'success');
        }
    }

    // 获取第一章内容
    async function fetchFirstChapter(url, titleSelector, contentSelector) {
        const dom = await fetchPage(url);
        if (!dom) return null;
        return extractChapterContent(dom, titleSelector, contentSelector);
    }

    // 初始化
    setTimeout(() => {
        createUI();
    }, 1000);
})();